package com.fll.fangyigateway.globalFilter;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fll.fangyicommon.entity.ResultOk;
import com.fll.fangyicommon.utils.JWTUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 将登录用户的JWT转化成用户信息的全局过滤器
 * @author fll
 * create 2023/2/25
 */
@Order(-1)
@Component
@Slf4j
public class LoginFilter implements GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //1.获取请求参数
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        //2.获取请求头中携带的token
        String token = request.getHeaders().getFirst("Authorization");

        //3.如果是登录(验证码登录或者密码)、验证码注册、webscokt聊天、重置密码，直接放行
        if (   request.getURI().getPath().contains("/verifyRegistered")
                || request.getURI().getPath().contains("/loginOrRegister")
                || request.getURI().getPath().contains("/sms/sendCode")
                || request.getURI().getPath().contains("/resetPass")
                || request.getURI().getPath().contains("/webscokt")
        ) {
            //向headers中放文件，记得build
            //此处向headers中存入请求的用户，将用户信息存入userStr（key: userInfo，value: userInfo）
            ServerHttpRequest req = exchange.getRequest().mutate().header("userInfo", "userInfo").build();
            exchange = exchange.mutate().request(req).build();
            return chain.filter(exchange);
        }

        ResultOk ok = new ResultOk();

        if (StringUtils.isEmpty(token)) {
            ok.setCode(333);
            ok.setMsg("鉴权失败，请先登录");

            byte[] bits = new byte[0];
            try {
                bits = new ObjectMapper().writeValueAsString(ok).getBytes(StandardCharsets.UTF_8);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            response.getHeaders().add("Content-Type", "text/json;charset=UTF-8");
            return response.writeWith(Mono.just(buffer));
        }
        try { //token不为空
            //从token中解析用户信息并设置到Header中去
            Claims claims = JWTUtil.parseJWT(token);
            String userInfo = claims.getSubject();

//            log.info("AuthGlobalFilter.filter() token:{}", token);
            log.info("AuthGlobalFilter.filter() user:{}", userInfo);

            ServerHttpRequest req = exchange.getRequest().mutate().header("userInfo", userInfo).build();
            exchange = exchange.mutate().request(req).build();
        } catch (Exception e) {
            ok.setCode(333);
            ok.setMsg("鉴权失败，请先登录");
            byte[] bits = new byte[0];
            try {
                bits = new ObjectMapper().writeValueAsString(ok).getBytes(StandardCharsets.UTF_8);
            } catch (JsonProcessingException ex) {
                ex.printStackTrace();
            }
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            response.getHeaders().add("Content-Type", "text/json;charset=UTF-8");
            return response.writeWith(Mono.just(buffer));
        }
        return chain.filter(exchange);
    }

}
